#pragma once
#include <atomic>
#include <cstdint>
#include <cstring>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include "Util.h"
#include "XnccType.h"
namespace xncc {
namespace sys {
    class EventFd;
}
namespace msg {
    class FIFOSafeElement;
    class FIFOSafeQueue
    {
      public:
        using s_ptr = std::shared_ptr<FIFOSafeQueue>;
        FIFOSafeQueue(types::queue_size_t size, bool autoExpand = false);
        ~FIFOSafeQueue() = default;

        void  write(const char* buffer, types::queue_size_t len);
        bool  tryWrite(const char* buffer, types::queue_size_t len);
        void  writeOver(types::queue_size_t len);
        void  writeOverNotNotify(types::queue_size_t len);
        char* read(types::queue_size_t len);
        void  readOver(types::queue_size_t len);
        void  setNeedNotify();

        [[nodiscard]] std::string dump() const;

        [[nodiscard]] types::queue_id_t id() const { return queueId_; }

        [[nodiscard]] std::shared_ptr<xncc::sys::EventFd> notifyId() const { return notifyfd_; }

      private:
        void updateReadPtr();
        void updateWritePtr();

      private:
        bool                                            autoExpand_;
        std::map<int, std::shared_ptr<FIFOSafeElement>> bufferList_;
        std::shared_ptr<xncc::sys::EventFd>             notifyfd_ = nullptr;
        std::shared_ptr<FIFOSafeElement>                readptr_;
        std::shared_ptr<FIFOSafeElement>                writeptr_;
        std::mutex                                      mutex_;
        int                                             lastReadIndex_;
        bool                                            isNeedNotify_;
        const types::queue_id_t                         queueId_;
    };
}  // namespace msg
}  // namespace xncc
